package myjdbc;

import java.sql.*;

/**
 * @Auther: cty
 * @Date: 2020/1/19 11:22
 * @Description:  测试事务
 * 1 什么是事务？
 * 事务是一组要么同时执行成功，要么同时执行失败的SQL语句，是数据库操作的一个执行单元。
 * 2 如何判断一个事务的开始和结束？
 * （1）事务开始
 *      * 连接到数据库后执行一条DML。
 *      * 前一个事务结束后执行一条DML。
 * （2）事务结束
 *      * 执行COMMIT语句（执行DDL、DCL后会自动执行COMMIT语句，或手动执行）。
 *      * 执行ROLLBACK语句（执行DML失败一般为其执行ROLLBACK语句）。
 *      * 断开与数据库的连接。
 * 3 事务的四大特点（ACID）
 * （1）atomicity（原子性）
 *      * 表示一个事务内的所有操作是一个整体，要么全部成功，要么全失败。
 * （2）consistency（一致性）
 *      * 表示一个事务内有一个操作失败时，所有的更改过的数据都必须回滚到修改前的状态。
 * （3）isolation（隔离性）
 *      * 一个事务查看数据时，数据所处的状态要么是另一并发事务修改它之前的状态，
 * 要么是修改之后的状态，而不会查看到修改的中间状态。
 * （4）durability（持久性）
 *      * 持久性事务完成之后，它对于系统的影响是永久性的。
 *
 * @version: 1.0
 */
public class JDBC_Demo05_Transaction{

    public static final String URL = "jdbc:mysql://localhost:3306/testjdbc";
    public static final String USER = "root";
    public static final String PASSWORD = "123456";

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1. 加载MySQL驱动程序
        Class.forName("com.mysql.jdbc.Driver");

        //2. 获得数据库连接
        Connection conn = DriverManager.getConnection(URL,USER,PASSWORD);

        //3. 操作数据库，通过PreparedStatement进行参数传递，实现插入记录
        PreparedStatement ps = null;
        PreparedStatement ps2 = null;
        try{
            conn.setAutoCommit(false);  //设置手动提交
            //存入第一条记录
            ps = conn.prepareStatement("insert into user(username,pwd,regTime,info) values(?,?,?,?)");
            ps.setObject(1,"张三");  //参数索引从1开始计算；setString可换为setObject，下同
            ps.setObject(2,"zs123");
            ps.setObject(3, new Date(System.currentTimeMillis()));
            ps.setObject(4,"我叫张三，今年三岁了。");
            ps.execute();
            System.out.println("存入一个用户，张三。");
            //暂停2s
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //存入第二条记录
            ps2 = conn.prepareStatement("insert into user(username,pwd,regTimestamp,infoVarchar) values(?,?,?,?,?)");  //设置异常！！！
            ps2.setObject(1,"李四");  //参数索引从1开始计算；setString可换为setObject，下同
            ps2.setObject(2,"ls123");
            ps2.setObject(3, new Date(System.currentTimeMillis()));
            ps2.setObject(4,"我叫李四，今年四岁了。");
            ps2.execute();
            System.out.println("存入一个用户，李四。");
            //提交
            conn.commit();
        }catch (Exception e){
            System.out.println("存入数据失败！");  //两条记录都插入失败
            conn.rollback();  //回滚
        }

        //4. 处理返回数据

        //5. 关闭连接
        if(ps!=null){
            ps.close();
        }
        if(ps2!=null){
            ps2.close();
        }
        if(conn!=null){
            conn.close();
        }
    }
}

/* res:
存入数据失败！
*/